perm filename SYMBOL.MSS[WHT,LSP] blob sn#754075 filedate 1984-05-12 generic text, type T, neo UTF8
@Part[Symbol, Root = "CLM.MSS"]
@Comment{Chapter of Common Lisp Manual.  Copyright 1984 Guy L. Steele Jr.⎇

@MyChapter[Symbols]
@Label{symbol⎇


A @xlisp symbol is a data object that has three user-visible
components:
@Begin[Itemize]
The @Def[property list] is a list that effectively provides each symbol
with many modifiable named components.

The @Def[print name] must be a string, which is the sequence of
characters used to identify the symbol.  Symbols are of great use
because a symbol can be located once its name is given
(typed, say, on a keyboard).
It is ordinarily not permitted to alter a symbol's print name.

The @Def[package cell] must refer to a package object.
A package is a data structure
used to locate a symbol once given the symbol's name.
A symbol is uniquely identified
by its name only when considered relative to a package.  A symbol may
appear in many packages, but it can be @i[owned] by at most one package.
The package cell points to the owner, if any.
Package cells are discussed along with packages in chapter @ref[XPACK].
@End[Itemize]

A symbol may actually have other components for use by the
implementation.  One of the more important uses of symbols is as
names for program variables; it is frequently desirable for the
implementor to use certain components of a symbol to implement
the semantics of variables.  See @Funref[symbol-value]
and @Funref[symbol-function].
However, there are several possible
implementation strategies, and so such possible components are not
described here.

@Section[The Property List]

Since its inception, @xlisp has associated with each symbol
a kind of tabular data structure
called a @Def[property list] (@Def[plist] for short).  A property list contains
zero or more entries; each entry associates with a key
(called the @Def[indicator]), which is typically
a symbol, an arbitrary @xLisp object (called the @i[value] or,
sometimes, the @Def[property]).
There are no duplications among the indicators; a property list may only
have one property at a time with a given name.  In this way, given
a symbol and an indicator (another symbol), an associated value can be
retrieved.

@Index2[P {property list⎇, S {compared to association list⎇]
A property
list is very similar in purpose to an association list.  The difference
is that a property list is an object with a unique identity; the
operations for adding and removing property-list entries are destructive
operations that alter the property list rather than making a new one.
Association lists, on the other hand, are normally augmented
non-destructively (without side effects) by adding new entries to the
front (see @Funref[acons] and @Funref[pairlis]).

A property list is implemented as a memory cell
containing a list with an even number (possibly zero) of elements.
(Usually this memory cell is the property-list cell of a symbol,
but any memory cell acceptable to @Macref[setf] can be used
if @Funref[getf] and @Macref[remf] are used.)
Each pair of elements in the list constitutes an entry;
the first item is the indicator, and the second is the
value.  Because property-list functions are given the symbol
and not the list itself, modifications to the property list
can be recorded by storing back into the property-list cell of the symbol.

When a symbol is created, its property list is initially empty.
Properties are created by using @Funref[get] within a @Macref[setf] form.

@clisp does not use a symbol's property list as extensively as earlier
@xlisp implementations did.  Less-used data, such as compiler,
debugging, and documentation information, is kept on property lists
in @clisp.
@Incompatibility{In older @xLisp implementations, the
print name, value, and function definition of a symbol were kept on its
property list.  The value cell was introduced into @maclisp and @interlisp
to speed up access to variables; similarly for the
print-name cell and function cell (@maclisp does not use a function cell).
Recent @xlisp implementations such as @slisp,
@lmlisp, and @newlisp have introduced all of these cells plus the
package cell.
None of the @Maclisp system property names
(@f[expr], @f[fexpr], @f[macro], @f[array],
@f[subr], @f[lsubr], @f[fsubr], and in former times @f[value] and
@f[pname]) exist in @clisp.⎇

@Incompatibility{In @clisp, the notion of ``disembodied property list''
introduced in @maclisp is eliminated.  It tended to be used for
rather kludgy things, and in @lmlisp is often associated with
the use of locatives (to make it ``off by one'' for searching
alternating keyword lists).  In @clisp special @f[setf]-like
property-list functions are introduced: @Funref[getf]
and @Macref[remf].⎇

@Defun[Fun {get⎇, Args {@i[symbol] @i[indicator] @optional @i[default]⎇]
@i[get] searches the property list of
@i[symbol] for an indicator @f[eq] to @i[indicator].
The first argument must be a symbol.
If one is found, then the corresponding value is returned;
otherwise @i[default] is returned.  If @i[default] is not specified,
then @false is used for @i[default].
Note that there is no way to distinguish an absent property from
one whose value is @i[default].
@Lisp
(get x y) @EQ (getf (symbol-plist x) y)
@Endlisp
Suppose that the property list of @f[foo] is @f[(bar t baz 3 hunoz "Huh?")].
Then, for example:
@Lisp
(get 'foo 'baz) @EV 3
(get 'foo 'hunoz) @EV "Huh?"
(get 'foo 'zoo) @EV @false
@Incompatibility{In @maclisp, the first argument to @f[get] could
be a list, in which case the @i[cdr] of the list was treated
as a so-called ``disembodied property list.''
The first argument to @f[get]
could also be any other object, in which case @f[get] would
always return @nil.  In @clisp, it is an error to give anything
but a symbol as the first argument to @f[get].

What @clisp calls @f[get], @interlisp calls @f[getprop].

What @maclisp and @interlisp call @f[putprop] is accomplished
in @clisp by using @f[get] with @f[setf].⎇
@Endlisp


@Macref[setf] may be used with @f[get] to create a new property-value
pair, possibly replacing an old pair with the same property name.
For example:
@lisp
(get 'clyde 'species) @EV @false
(setf (get 'clyde 'species) 'elephant) @EV elephant
@r[and now] (get 'clyde 'species) @EV elephant
@endlisp
The @i[default] argument may be
specified to @f[get] in this context; it is ignored by @f[setf], but
may be useful in such macros as @f[push] that are related to @f[setf]:
@lisp
(push item (get sym 'token-stack '(initial-item)))
@endlisp
means the approximately the same as
@lisp
(setf (get sym 'token-stack '(initial-item))
      (cons item (get sym 'token-stack '(initial-item))))
@endlisp
which in turn would be treated as simply
@lisp
(setf (get sym 'token-stack)
      (cons item (get sym 'token-stack '(initial-item))))
@endlisp
@Enddefun

@Defun[Fun {remprop⎇, Args {@i[symbol] @i[indicator]⎇]
This removes from @i[symbol] the property with an indicator @f[eq]
to @i[indicator].  The property indicator and the corresponding
value are removed by destructively splicing the property
list.  It returns @false if no such property was found,
or non-@false if a property was found.
@Lisp
(remprop x y) @EQ (remf (symbol-plist x) y)
@Endlisp
For example, if the property list of @f[foo] is initially
@lisp
(color blue height 6.3 near-to bar)
@endlisp
then the call
@lisp
(remprop 'foo 'height)
@endlisp
returns a non-@nil value after altering @f[foo]'s property list to be
@lisp
(color blue near-to bar)
@Endlisp
@Enddefun

@Defun[Fun {symbol-plist⎇, Args {@i[symbol]⎇]
This returns the list that contains the property pairs of @i[symbol];
the contents of the property-list cell are extracted and returned.

Note that using @f[get] on the result of @f[symbol-plist] does @i[not] work.
One must give the symbol itself to @f[get] or else
use the function @Funref[getf].

@Macref[setf] may be used with @f[symbol-plist] to destructively replace
the entire property list of a symbol.  This is a relatively dangerous
operation, as it may destroy important information that
the implementation may happen to store in property lists.
Also, care must be taken that the new
property list is in fact a list of even length.
@Incompatibility{In @maclisp, this function is called @f[plist];
in @interlisp, it is called @f[getproplist].⎇
@Enddefun

@Defun[Fun {getf⎇, Args {@i[place] @i[indicator] @optional @i[default]⎇]
@f[getf] searches the property list stored in @i[place]
for an indicator @f[eq] to @i[indicator].
If one is found, then the corresponding value is returned;
otherwise @i[default] is returned.  If @i[default] is not specified,
then @false is used for @i[default].
Note that there is no way to distinguish an absent property from
one whose value is @i[default].
Often @i[place] is computed from
a generalized variable acceptable to @Macref[setf].

@Macref[setf] may be used with @f[getf], in which case the @i[place] must
indeed be acceptable as a @i[place] to @f[setf].  The effect is to
add a new property-value pair, or update an existing pair,
in the property list kept in the @i[place].
The @i[default] argument may be
specified to @f[getf] in this context; it is ignored by @f[setf] but
may be useful in such macros as @f[push] that are related to @f[setf].
See the description of @Funref[get] for an example of this.

@Incompatibility{The @interlisp function @f[listget] is similar to @f[getf].
The @interlisp function @f[listput] is similar to using @f[getf]
with @f[setf].⎇
@Enddefun

@Defmac[Fun {remf⎇, Args {@i[place] @i[indicator]⎇]
This removes from the property list stored in @i[place]
the property with an indicator @f[eq]
to @i[indicator].  The property indicator and the corresponding
value are removed by destructively splicing the property
list.  @f[remf] returns @false if no such property was found,
or some non-@nil value if a property was found.
The form @i[place] may be any generalized variable acceptable to @Macref[setf].
See @Funref[remprop].
@Enddefmac

@Defun[Fun {get-properties⎇, Args {@i[place] @i[indicator-list]⎇]
@f[get-properties] is like @Funref[getf], except that the second
argument is a list of indicators.  @f[get-properties] searches the
property list stored in @i[place] for any of the indicators in
@i[indicator-list] until it finds the first property
in the property list whose indicator is one of
the elements of @i[indicator-list].  Normally @i[place] is computed from
a generalized variable acceptable to @Macref[setf].

@f[get-properties] returns three values.
If any property was found, then
the first two values are the indicator
and value for the first property whose indicator was in @i[indicator-list],
and the third is that tail of the property list whose @i[car]
was the indicator (and whose @i[cadr] is therefore the value).
If no property was found, all three values are @nil.
Thus the third value serves as a flag indicating success or failure
and also allows the search to be restarted after the property found
if desired.
@Enddefun

@Section[The Print Name]
@index[print name]
Every symbol has an associated string called the @i[print name].
This string is used as the external representation of the symbol:
if the characters in the string are typed in to @f[read]
(with suitable escape conventions for certain characters),
it is interpreted as a reference to that symbol
(if it is interned); and if the symbol is printed, @f[print] types out the
print name.
For more information, see the sections on the @i[reader]
(section @ref[READER])
and @i[printer] (section @ref[PRINTER]).

@Defun[Fun {symbol-name⎇, Args {@i[sym]⎇]
This returns the print name of the symbol @i[sym].
For example:
@Lisp
(symbol-name 'xyz) @EV "XYZ"
@Endlisp
It is an extremely bad idea to modify a string being used as the print name of
a symbol.  Such a modification may tremendously confuse
the function @Funref[read] and the package system.
@Enddefun

@Section[Creating Symbols]

Symbols can be used in two rather different ways.
An @i[interned] symbol is one that is indexed by its print name
in a catalogue called a @i[package].
Every time anyone asks for a symbol with that print name,
he gets the same (@f[eq]) symbol.  Every time input is read with the
function @Funref[read],
and that print name appears, it is read as the same symbol.
This property of symbols makes them appropriate to use as names for
things and as hooks on which to hang permanent data objects
(using the property list, for example).

Interned symbols are normally created automatically; the first time
something (such as the function @f[read])
asks the package system for a symbol with a given print name,
that symbol is automatically created.  The function used to ask for
an interned symbol is @Funref[intern], or one of the functions
related to @f[intern].

Although interned symbols are the most commonly
used, they will not be discussed further here.  For more information,
see chapter @ref[XPACK].

An @i[uninterned] symbol is a symbol used simply as a data object,
with no special cataloguing (it belongs to no particular package).
An uninterned symbol is printed as @f[#:] followed by its
print name.
The following are some functions for creating uninterned symbols.

@Defun[Fun {make-symbol⎇, Args {@i[print-name]⎇]
@f[(make-symbol @i[print-name])] creates a new uninterned symbol, whose
print name is the string @i[print-name].  The value and function bindings will
be unbound and the property list will be empty.

The string actually installed in the symbol's print-name component
may be the given string @i[print-name] or may be a copy of it,
at the implementation's discretion.  The user should not assume
that @f[(symbol-name (make-symbol x))] is @f[eq] to @f[x], but also
should not alter a string once it has been given as an argument
to @f[make-symbol].
@Implementation{An implementation might choose, for example,
to copy the string to some read-only area, in the expectation that
it will never be altered.⎇
@Incompatibility{@lmlisp uses the second argument for an odd flag
related to areas.  It is unclear what @newlisp does about this.⎇
@Enddefun

@Defun[Fun {copy-symbol⎇, Args {@i[sym] @optional @i[copy-props]⎇]
This returns a new uninterned symbol with the same print name
as @i[sym].  If @i[copy-props] is non-@nil, then the initial
value and function definition of the new symbol will
be the same as those of @i[sym], and the property list of
the new symbol will be a copy of @i[sym]'s.  If @i[copy-props]
is @nil (the default), then the new symbol will be unbound and undefined, and
its property list will be empty.
@Enddefun

@Defun[Fun {gensym⎇, Args {@optional @i[x]⎇]
@f[gensym] invents a print name and creates a new symbol with that print name.
It returns the new, uninterned symbol.

The invented print name consists of a prefix
(which defaults to @f[G]), followed by the decimal representation of a number.
The number is increased by one every time @f[gensym] is called.

If the argument @i[x] is present and is an integer, then @i[x] must be
non-negative, and the internal counter is set to @i[x] for future use;
otherwise the internal counter is incremented.
If @i[x] is a string, then that string is made the default prefix
for this and future calls to @f[gensym].
After handling the argument, @f[gensym] creates a
symbol as it would with no argument.
For example:
@lisp
(gensym) @EV G7
(gensym "FOO-") @EV FOO-8
(gensym 32) @EV FOO-32
(gensym) @EV FOO-33
(gensym "GARBAGE-") @EV GARBAGE-34
@Endlisp

@f[gensym] is usually used to create a symbol that should not normally
be seen by the user and whose print name is unimportant except to
allow easy distinction by eye between two such symbols.
The optional argument is rarely supplied.
The name comes from ``generate symbol,'' and the symbols produced by it
are often called ``gensyms.''

@Incompatibility{In earlier versions of @xlisp, such as @maclisp and
@interlisp, the print name of a gensym was of fixed length, consisting
of a single letter and a fixed-length
decimal representation with leading zeros
if necessary, for example, @f[G0007].  This convention was
motivated by an implementation consideration, namely that the name
should fit into a single machine word, allowing a quick and clever
implementation.  Such considerations are less relevant in @clisp.
The consistent use of a mnemonic prefixes can make it easier
for the programmer, when debugging, to determine what code generated
a particular symbol.  The elimination of the fixed-length decimal
representation prevents the same name from being used twice
unless the counter is explicitly reset.⎇

If it is desirable
for the generated symbols to be interned, and yet guaranteed to be
symbols distinct from all others,
then the function @Funref[gentemp]
may be more appropriate to use.
@Enddefun

@Defun[Fun {gentemp⎇, Args {@optional @i[prefix] @i[package]⎇]
@f[gentemp], like @Funref[gensym], creates and returns a new symbol.
@f[gentemp] differs from @f[gensym] in that it interns the symbol
(see @Funref[intern]) in the @i[package] (which defaults to the current
package; see @Varref[package]).  @f[gentemp] guarantees the symbol
will be a new one not already existing in the package.  It does this
by using a counter as @f[gensym] does, but if the generated symbol
is not really new, then the process is repeated until a new one is created.
There is no provision for resetting the @f[gentemp] counter.
Also, the prefix for @f[gentemp] is not remembered from one call
to the next; if @i[prefix] is omitted, the default prefix @f[T] is used.
@Enddefun

@Defun[Fun {symbol-package⎇, Args {@i[sym]⎇]
Given a symbol @i[sym], @f[symbol-package] returns the contents of the
package cell of that symbol.  This will be a package object or @nil.
@Enddefun

@Defun[Fun {keywordp⎇, Args {@i[object]⎇]
The argument may be any @xlisp object.  The predicate @f[keywordp] is true
if the argument is a symbol and that
symbol is a keyword (that is, belongs to the keyword
package).  Keywords are those symbols that are written with
a leading colon.  Every keyword is a constant, in the sense
that it always evaluates to itself.  See @Funref[constantp].
@Enddefun